﻿package code {
	import flash.geom.Rectangle;
	import flash.events.*;	
	// creates the ball
	public class Ball extends GameObject {
		private const GRAVITY:Number = 10;
		private const MAX_FALL:Number = 50;
		private const BOUNCE:Number = -.9;
		private var mass:int;
		public var isReset, launched, gravityIsOn, hasLaunched:Boolean;	  // reset, launched, gravity on, and launched
		
		//HUD Update variables
		public var score:Number = 0;
		public var ballsLeft:Number = 3;
		
		//Collision variables
		private var xBound:Number = 665;
		private var radius:Number = 30;
		
		
		public function Ball(shapeType:String, radius:Number, sides:Number, color:uint, thickness:Number, hollow:Boolean) {
			super(shapeType, radius, sides, color, thickness, hollow);
			mass = 200;
			gravityIsOn = true;
			isReset = true; //Is the ball being reset?
		}
		
		
		// update method for ball, takes in collision objects and update time
		public function update(collisionObjects:Array, currentTime:Number){
			currentTime = currentTime / 100;
			
			//Normal checks if not being reset
			if(isReset == true)
			{
				moveBall(currentTime);
				
				checkCollision(collisionObjects);
				
				checkSides();
			}
			
		}
		
		// moves the ball using euler and time
		public function moveBall(currentTime:Number){
			if(gravityIsOn && vy < MAX_FALL){
				vy += GRAVITY;
			}
			
			x += vx * currentTime;  // changes velocity over time
			y += vy * currentTime;			
		}
		
		// checks all collision
		public function checkCollision(collisionObjects:Array){		
			for each(var go:GameObject in collisionObjects)
			{
				var dx:Number = go.x - x;
				var dy:Number = go.y - y;
				var dist:Number = Math.sqrt(dx*dx + dy*dy);
				if(hitTestObject(go)){  // then there is collision					
					for each(var l:Line in go.shape.linesArray){
						if(l.a != null && l.b != null)
							if(checkLine(l)){								
								if(go is Bar){
									var tempBar = go as Bar;
									tempBar.vx = Math.abs(((tempBar.mass - mass) * vx + 2 * (tempBar.mass * vx)) / (mass + tempBar.mass));  // gets the velocity of the ball on the bar
									tempBar.vy = Math.abs(((tempBar.mass - mass) * vy + 2 * (tempBar.mass * vy)) / (mass + tempBar.mass));  // uses linear momentum
									
									var velocityVertex = new Vertex(tempBar.vx, tempBar.vy);   // make a "vector" out of total velocity
									
									var barMomentum:Number = Vertex.getMagnitude(velocityVertex) * tempBar.mass;  // gets linear momentum
									
									var leverArmDisplacement:Number = Vertex.displace(new Vertex(x, y), tempBar.topLeftVertex);  // displaces from the ball to the bar topLeftVertex (the pivot point)

									var rotationMomentum:Number = leverArmDisplacement * barMomentum;  // will always hit on end of bar
									var omega = rotationMomentum / tempBar.getInertia(leverArmDisplacement);    // solve for omega = L / I
									tempBar.omega += omega;  // add to the omega
								}
								break;  // stops checking for collision
							}
					}					
				}
			}
		}

		// checks against lines the array
		public function checkLine(line:Line):Boolean{
			
			if(hitTestObject(line)){  // from schwartz
				
				var angle:Number = line.getAngle();

				var cos:Number = Math.cos(angle);
				var sin:Number = Math.sin(angle);
				
				var x1:Number = x - line.a.x;
				var y1:Number = y - line.a.y;
				
				var y2:Number = cos * y1 - sin * x1;
				
				var vy1:Number = cos * vy - sin * vx;
				
				if((y2 > -shape.radius && y2 < vy1)){
					var x2:Number = cos * x1 + sin * y1;
					
					var vx1:Number = cos * vx + sin * vy;
					
					y2 = -shape.radius;
					
					vy1 *= BOUNCE;  // fakes linear momentum with ball
					x1 = cos * x2 - sin * y2;
					y1 = cos * y2 + sin * x2;
					vx = cos * vx1 - sin * vy1;
					vy = cos * vy1 + sin * vx1;
					x = line.a.x + x1;
					y = line.a.y + y1;
					return true;
				}
			}
			return false;
		}
		
		// bounding for the stage
		public function checkSides():void
		{
			if(x + shape.radius > stage.stageWidth)
			{
				x = stage.stageWidth - shape.radius;
				vx *= BOUNCE;
			}
			else if(x - shape.radius < 0)
			{
				x = shape.radius;
				vx *= BOUNCE;
			}
			if(y + shape.radius > stage.stageHeight)
			{
				y = stage.stageHeight - shape.radius;
				vy *= BOUNCE;
			}
			else if(y - shape.radius < 0)
			{
				y = shape.radius;
				vy *= BOUNCE;
			}
		}
	}	
}
